package com.orange.lswidget;

import java.io.File;
import java.util.HashSet;
import java.util.Set;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;

import com.orange.lswidget.widgets.event.manager.EventManager;
import com.orange.lswidget.widgets.musicplayer.entry.MusicPlayer;
import com.orange.notificationsummary.utils.Constants;
import com.orange.util.LogHelper;
import com.orange.util.MusicUtils;

public class LSWidgetContentProvider extends ContentProvider {
	private static final String		TAG									= "LSWidgetContentProvider";

	private static final String		LOCKSCREEN_DB_NAME					= "lockscreen.db";

	private static final String		WALLPAPER_TABLE_NAME				= "wallpaper";
	private static final String		MUSIC_TABLE_NAME					= "musicplayer";
	private static final String		NOTIFICATION_TABLE_NAME				= "notification";

	/** Current database version */
	private static final int		DB_VERSION							= 103;
	/** Database version from which upgrading is a nop */
	private static final int		DB_VERSION_NOP_UPGRADE_FROM			= 31;
	/** Database version to which upgrading is a nop */
	private static final int		DB_VERSION_NOP_UPGRADE_TO			= 100;

	private SQLiteOpenHelper		mOpenHelper							= null;

	/** URI matcher used to recognize URIs sent by applications */
	private static final UriMatcher	URI_MATCHER							= new UriMatcher(
																				UriMatcher.NO_MATCH);

	private static final int		WALLPAPER_ITEM						= 1;
	private static final int		MUSIC_ITEM							= 2;
	private static final int		NOTIFICATION_ITEM					= 3;

	static {
		URI_MATCHER.addURI(Constants.AUTHORITY, "wallpaper", WALLPAPER_ITEM);
		URI_MATCHER.addURI(Constants.AUTHORITY, "musicplayer", MUSIC_ITEM);
		URI_MATCHER.addURI(Constants.AUTHORITY, "notification",
				NOTIFICATION_ITEM);
	}

	/** for music */
	private static final String[]	MUSICPLAYER_READABLE_COLUMNS_ARRAY	= new String[] {
			MusicPlayer._ID, MusicPlayer.COLUMN_MUSIC_TRACK_SELECTED	};
	private static Set<String>		sMusicReadableColumnsSet;
	static {
		sMusicReadableColumnsSet = new HashSet<String>();
		for (int i = 0; i < MUSICPLAYER_READABLE_COLUMNS_ARRAY.length; i++) {
			sMusicReadableColumnsSet.add(MUSICPLAYER_READABLE_COLUMNS_ARRAY[i]);
		}
	}

	/** for wallpaper */
	private static final String[]	WALLPAPER_READABLE_COLUMNS_ARRAY	= new String[] {
			WallPaper._ID, WallPaper.COLUMN_WALLPAPER_PICTURE			};
	private static Set<String>		sWallpaperReadableColumnsSet;
	static {
		sWallpaperReadableColumnsSet = new HashSet<String>();
		for (int i = 0; i < WALLPAPER_READABLE_COLUMNS_ARRAY.length; i++) {
			sWallpaperReadableColumnsSet
					.add(WALLPAPER_READABLE_COLUMNS_ARRAY[i]);
		}
	}

	/** for notification */
	public static final String[]	NOTIFICATION_READABLE_COLUMNS_ARRAY	= new String[] {
			EventManager._ID, EventManager.COLUMN_NOTIFICATION_COUNT,
			EventManager.COLUMN_UNREADMMS_COUNT,
			EventManager.COLUMN_MISSCALL_COUNT,
			EventManager.COLUMN_VOICEMAI_COUNT							};

	private static Set<String>		sNotificationReadableColumnsSet;
	static {
		sNotificationReadableColumnsSet = new HashSet<String>();
		for (int i = 0; i < NOTIFICATION_READABLE_COLUMNS_ARRAY.length; i++) {
			sNotificationReadableColumnsSet
					.add(NOTIFICATION_READABLE_COLUMNS_ARRAY[i]);
		}
	}

	@Override
	public boolean onCreate() {
		mOpenHelper = new DatabaseHelper(getContext());
		return true;
	}

	@Override
	public Uri insert(Uri uri, ContentValues values) {
		SQLiteDatabase db = mOpenHelper.getWritableDatabase();
		Context context = getContext();
		Uri ret = null;
		int match = URI_MATCHER.match(uri);

		switch (match) {
		case WALLPAPER_ITEM:
			break;
		case MUSIC_ITEM:
			ContentValues musicValues = new ContentValues();
			copyString(MusicPlayer.COLUMN_MUSIC_TRACK_SELECTED, values,
					musicValues);

			long rowId = db.insert(MUSIC_TABLE_NAME, null, musicValues);
			if (rowId != -1) {
				ret = Uri.parse(MusicPlayer.CONTENT_URI + "/" + rowId);
				context.getContentResolver().notifyChange(uri, null);
			} else {
				LogHelper
						.e(TAG,
								"insert. Failed to insert new rows to 'musicplayer' table");
			}
			break;
		case NOTIFICATION_ITEM:
			ContentValues ntfcValues = new ContentValues();
			copyString(EventManager.COLUMN_NOTIFICATION_COUNT, values,
					ntfcValues);

			long rowNoId = db.insert(NOTIFICATION_TABLE_NAME, null, ntfcValues);
			if (rowNoId != -1) {
				ret = Uri.parse(EventManager.CONTENT_URI + "/" + rowNoId);
				context.getContentResolver().notifyChange(uri, null);
			} else {
				LogHelper
						.e(TAG,
								"insert. Failed to insert new rows to 'notification' table");
			}
			break;
		default:
			LogHelper.e(TAG,
					"insert. calling insert on an unknown/invalid URI: " + uri);
			throw new IllegalArgumentException("Unknown/Invalid URI " + uri);
		}

		return ret;
	}

	@Override
	public int delete(Uri uri, String selection, String[] selectionArgs) {
		SQLiteDatabase db = mOpenHelper.getWritableDatabase();
		int match = URI_MATCHER.match(uri);
		int result = 0;
		switch (match) {
		case WALLPAPER_ITEM:
			// result = db.delete(WALLPAPER_TABLE_NAME, selection,
			// selectionArgs);
			break;
		case MUSIC_ITEM:
			result = db.delete(MUSIC_TABLE_NAME, selection, selectionArgs);
			break;
		case NOTIFICATION_ITEM:
			result = db.delete(NOTIFICATION_TABLE_NAME, selection,
					selectionArgs);
			break;
		default:
			break;
		}
		return result;
	}

	@Override
	public int update(Uri uri, ContentValues values, String selection,
			String[] selectionArgs) {
		SQLiteDatabase db = mOpenHelper.getWritableDatabase();
		int match = URI_MATCHER.match(uri);
		int result = 0;

		switch (match) {
		case WALLPAPER_ITEM:
			byte[] data = MusicUtils
					.getByteFromFile(WallPaper.GALLERY_WALLPAPER_PATH);
			if (data != null) {
				db.delete(WALLPAPER_TABLE_NAME, null, null);

				ContentValues wpValues = new ContentValues();
				wpValues.put(WallPaper.COLUMN_WALLPAPER_PICTURE, data);
				if (-1 == db.insert(WALLPAPER_TABLE_NAME, null, wpValues)) {
					db.close();
					return result;
				}
				db.close();
				final File file = new File(WallPaper.GALLERY_WALLPAPER_PATH);
				if (file.exists()) {
					try {
						file.delete();
					} catch (Exception e) {
					}
				}
				result = 1;
			}
			break;
		case MUSIC_ITEM:
			result = db.update(MUSIC_TABLE_NAME, values, selection,
					selectionArgs);
			break;
		case NOTIFICATION_ITEM:
			result = db.update(NOTIFICATION_TABLE_NAME, values, selection,
					selectionArgs);
			break;
		default:
			LogHelper.e(TAG, "update. updating unknown URI: " + uri);
			throw new IllegalArgumentException("Unknown URI: " + uri);
		}

		return result;
	}

	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder) {
		String[] tempProjection = projection;

		SQLiteDatabase db = mOpenHelper.getReadableDatabase();
		SQLiteQueryBuilder builder = new SQLiteQueryBuilder();

		int match = URI_MATCHER.match(uri);
		switch (match) {
		case WALLPAPER_ITEM:
			builder.setTables(WALLPAPER_TABLE_NAME);
			if (tempProjection == null) {
				tempProjection = WALLPAPER_READABLE_COLUMNS_ARRAY;
			} else {
				for (int i = 0; i < tempProjection.length; i++) {
					if (!sWallpaperReadableColumnsSet
							.contains(tempProjection[i])) {
						throw new IllegalArgumentException("column "
								+ tempProjection[i] + " does not exists!");
					}
				}
			}
			break;
		case MUSIC_ITEM:
			builder.setTables(MUSIC_TABLE_NAME);
			if (tempProjection == null) {
				tempProjection = MUSICPLAYER_READABLE_COLUMNS_ARRAY;
			} else {
				for (int i = 0; i < tempProjection.length; i++) {
					if (!sMusicReadableColumnsSet.contains(tempProjection[i])) {
						throw new IllegalArgumentException("column "
								+ tempProjection[i] + " does not exists!");
					}
				}
			}
			break;
		case NOTIFICATION_ITEM:
			builder.setTables(NOTIFICATION_TABLE_NAME);
			if (tempProjection == null) {
				tempProjection = NOTIFICATION_READABLE_COLUMNS_ARRAY;
			} else {
				for (int i = 0; i < tempProjection.length; i++) {
					if (!sNotificationReadableColumnsSet
							.contains(tempProjection[i])) {
						throw new IllegalArgumentException("column "
								+ tempProjection[i] + " does not exists!");
					}
				}
			}
			break;
		default:
			LogHelper.e(TAG, "query. querying unknown URI: " + uri);
			throw new IllegalArgumentException("Unknown URI: " + uri);
		}

		Cursor cursor = builder.query(db, tempProjection, selection,
				selectionArgs, null, null, sortOrder);

		if (cursor != null) {
			cursor.setNotificationUri(getContext().getContentResolver(), uri);
		} else {
			LogHelper.e(TAG, "query. query failed in downloads database");
		}

		return cursor;
	}

	private void copyString(String column, ContentValues from, ContentValues to) {
		String s = from.getAsString(column);
		if (s != null) {
			to.put(column, s);
		}
	}

	@Override
	public String getType(Uri uri) {
		return null;
	}

	private final class DatabaseHelper extends SQLiteOpenHelper {
		public DatabaseHelper(final Context context) {
			super(context, LOCKSCREEN_DB_NAME, null, DB_VERSION);
		}

		@Override
		public void onCreate(final SQLiteDatabase db) {
			LogHelper.v(TAG, "populating new database");
			createTable(db);
		}

		@Override
		public void onUpgrade(final SQLiteDatabase sqliteDB, int oldVersion,
				final int newVersion) {
			if (oldVersion == DB_VERSION_NOP_UPGRADE_FROM) {
				if (newVersion == DB_VERSION_NOP_UPGRADE_TO) {
					return;
				}
				oldVersion = DB_VERSION_NOP_UPGRADE_TO;
			}
			LogHelper.i(TAG,
					"onUpgrade. Upgrading downloads database from version "
							+ oldVersion + " to " + newVersion
							+ ", which will destroy all old data");
			dropTable(sqliteDB);
			createTable(sqliteDB);
		}
	}

	private void createTable(SQLiteDatabase db) {
		// create musicplayer table
		try {
			db.execSQL("CREATE TABLE " + MUSIC_TABLE_NAME + "("
					+ MusicPlayer._ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
					+ MusicPlayer.COLUMN_MUSIC_TRACK_SELECTED + " TEXT);");

			ContentValues values = new ContentValues();
			values.put(MusicPlayer.COLUMN_MUSIC_TRACK_SELECTED, "false");
			db.insert(MUSIC_TABLE_NAME, null, values);
		} catch (SQLException ex) {
			LogHelper.e(TAG,
					"createTable. Failed to create musicplayer table. ", ex);
			throw ex;
		}

		// create notification table
		try {
			db.execSQL("CREATE TABLE " + NOTIFICATION_TABLE_NAME + "("
					+ EventManager._ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
					+ EventManager.COLUMN_NOTIFICATION_COUNT + " integer,"
					+ EventManager.COLUMN_UNREADMMS_COUNT + " integer,"
					+ EventManager.COLUMN_MISSCALL_COUNT + " integer,"
					+ EventManager.COLUMN_VOICEMAI_COUNT + " integer" + ");");

			ContentValues values = new ContentValues();
			values.put(EventManager.COLUMN_NOTIFICATION_COUNT, 0);
			db.insert(NOTIFICATION_TABLE_NAME, null, values);
		} catch (SQLException ex) {
			LogHelper.e(TAG,
					"createTable. Failed to create notification table. ", ex);
			throw ex;
		}

		// create wallpaper table
		try {
			db.execSQL("CREATE TABLE " + WALLPAPER_TABLE_NAME
					+ "(_id INTEGER PRIMARY KEY, "
					+ WallPaper.COLUMN_WALLPAPER_PICTURE + " TEXT);");
		} catch (SQLException ex) {
			LogHelper.e(TAG, "createTable. Failed to create wallpaper table. ",
					ex);
			throw ex;
		}
	}

	private void dropTable(SQLiteDatabase db) {
		try {
			db.execSQL("DROP TABLE IF EXISTS " + WALLPAPER_TABLE_NAME);
			db.execSQL("DROP TABLE IF EXISTS " + MUSIC_TABLE_NAME);
			db.execSQL("DROP TABLE IF EXISTS " + NOTIFICATION_TABLE_NAME);
		} catch (SQLException ex) {
			LogHelper.e(TAG,
					"dropTable. Failed to drop table in downloads database ",
					ex);
			throw ex;
		}
	}

}
